﻿using System;
using System.IO;
using System.Xml;
using System.Text;
using SZJT.Framework.Services;

namespace SZJT.Framework.Core
{
    public class XmlTransformMessage : MessageBase
    {
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(
                new XmlHelper.XmlElement(Constants.SingleMessageRootName)
                    .AddAttribute(Constants.TaskGuidName, TaskGuid)
                    .AddAttribute(Constants.DataGuidName, DataGuid)
                    .AddAttribute(Constants.DataTypeName, DataType)
                    .ToString());
            
            if (!string.IsNullOrEmpty(XmlTransformElementsRootName))
            {
                sb.Append(XmlHelper.GetElementString(XmlTransformElementsRootName));
            }

            foreach (XmlDataElement element in Elements)
            {
                sb.Append(element.ToString());
            }

            if (!string.IsNullOrEmpty(XmlTransformElementsRootName))
            {
                sb.Append(XmlHelper.GetEndElementString(XmlTransformElementsRootName));
            }

            sb.Append(XmlHelper.GetEndElementString(Constants.SingleMessageRootName));

            return sb.ToString();
        }

        public static XmlTransformMessage Parse(string xml)
        {
            XmlTransformMessage message = null;

            XmlReader reader = XmlTextReader.Create(new StringReader(xml));

            try
            {
                if (reader.Read())
                {
                    if (reader.Name == Constants.SingleMessageRootName)
                    {
                        message = new XmlTransformMessage();
                        message.TaskGuid = reader.GetAttribute(Constants.TaskGuidName);
                        message.DataGuid = reader.GetAttribute(Constants.DataGuidName);
                        message.DataType = reader.GetAttribute(Constants.DataTypeName);
                    }
                    else
                    {
                        ServiceExceptionHelper.ThrowXmlErrorException(
                            string.Format("XmlTranform root node must be '{0}'.", Constants.SingleMessageRootName));
                    }
                }
                if (message != null)
                {
                    if (reader.Read() && !reader.HasAttributes)
                    {
                        message.XmlTransformElementsRootName = reader.Name;
                    }
                    else
                    {
                        AddElement(reader, message);
                    }

                    while (reader.Read())
                    {
                        AddElement(reader, message);
                    }
                }
            }
            catch (XmlException xmlException)
            {
                ServiceExceptionHelper.ThrowXmlErrorException(xmlException.Message);
            }
            catch
            {
                throw;
            }
            finally
            {
                reader.Close();
            }

            return message;
        }

        public static void AddElement(XmlReader reader, XmlTransformMessage message)
        {
            if (reader.NodeType != XmlNodeType.Element) return;
            var element = new XmlDataElement { Name = reader.Name };
            if(reader.HasAttributes)
            {
                var dataTypeStr = reader.GetAttribute(Constants.TypeName);
                if (! string.IsNullOrEmpty(dataTypeStr))
                {
                    try
                    {
                        element.ServiceDataType = (ServiceDataType)Enum.Parse(typeof(ServiceDataType), dataTypeStr);
                    }
                    catch
                    {
                        element.ServiceDataType = ServiceDataType.UNKNOWN;
                    }
                }
            }
            else
                element.ServiceDataType = ServiceDataType.UNKNOWN;
            element.Value = reader.ReadString();
            message.Elements.Add(element);
        }
    }
}
